package com.example.session

import java.util.*

/**
 * Mesh地址
 * Mesh地址类似IP地址
 * 内存格式：
 *      地址 10.0.0.1
 *      内存 { 0x01, 0x00, 0x00, 0x0A }
 */
open class MeshAddress {

    private val data = ByteArray(ADDRESS_SIZE)

    constructor()

    constructor(addressBuffer: ByteArray) {
        setData(addressBuffer)
    }

    constructor(addressString: String) {
        if (addressString.contains(".")) {
            // 0A:0B:0C:0D
            val splits = addressString.split("\\.".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
            if (splits.size != ADDRESS_SIZE)
                throw IllegalArgumentException(addressString + "is illegal format")

            setData(byteArrayOf(Integer.parseInt(splits[3], 10).toByte(), Integer.parseInt(splits[2], 10).toByte(), Integer.parseInt(splits[1], 10).toByte(), Integer.parseInt(splits[0], 10).toByte()))
        } else {
            val size = addressString.length
            if (size != 8)
                throw IllegalArgumentException(addressString + "is illegal format")

            setData(byteArrayOf(Integer.parseInt(addressString.substring(6, size), 10).toByte(), Integer.parseInt(addressString.substring(4, size - 2), 10).toByte(), Integer.parseInt(addressString.substring(2, size - 4), 10).toByte(), Integer.parseInt(addressString.substring(0, size - 6), 10).toByte()))
        }
    }

    override fun equals(other: Any?): Boolean {
        try {
            if (other is MeshAddress) {
                return Arrays.equals(data, other.getData())
            } else if (other is String) {
                return toString().equals(other.toString(), ignoreCase = true)
            } else if (other is ByteArray) {
                return Arrays.equals(data, other as ByteArray?)
            }
        } catch (e: IllegalArgumentException) {
            return false
        }

        return false
    }

    override fun toString(): String {

        val a = (data[3].toInt() and 0xFF)
        val b = (data[2].toInt() and 0xFF)
        val c = (data[1].toInt() and 0xFF)
        val d = (data[0].toInt() and 0xFF)
        return "$a.$b.$c.$d"
    }

    override fun hashCode(): Int {
        return Arrays.hashCode(data)
    }

    fun getData(): ByteArray {
        return data
    }

    fun setData(address: ByteArray?) {
        if (address == null)
            throw IllegalArgumentException("Address is null")

        if (address.size != ADDRESS_SIZE)
            throw IllegalArgumentException("Illegal address size")

        this.data[0] = address[0]
        this.data[1] = address[1]
        this.data[2] = address[2]
        this.data[3] = address[3]
    }

    companion object {

        private const val ADDRESS_SIZE = 4
    }
}